package com.wande.dataplatform.filecollection.performance;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 性能监控器
 * 用于收集和统计文件采集的性能指标
 *
 * @author wande
 */
@Slf4j
@Component
public class PerformanceMonitor {

    /**
     * 任务性能指标
     */
    private final Map<Long, TaskMetrics> taskMetricsMap = new ConcurrentHashMap<>();

    /**
     * 全局性能指标
     */
    private final GlobalMetrics globalMetrics = new GlobalMetrics();

    /**
     * 开始监控任务
     */
    public void startTask(Long taskId) {
        TaskMetrics metrics = new TaskMetrics();
        metrics.setTaskId(taskId);
        metrics.setStartTime(System.currentTimeMillis());
        taskMetricsMap.put(taskId, metrics);
    }

    /**
     * 结束监控任务
     */
    public void endTask(Long taskId, boolean success) {
        TaskMetrics metrics = taskMetricsMap.get(taskId);
        if (metrics != null) {
            metrics.setEndTime(System.currentTimeMillis());
            metrics.setSuccess(success);
            
            // 更新全局指标
            globalMetrics.totalTasks.incrementAndGet();
            if (success) {
                globalMetrics.successTasks.incrementAndGet();
            } else {
                globalMetrics.failedTasks.incrementAndGet();
            }
            
            long duration = metrics.getEndTime() - metrics.getStartTime();
            globalMetrics.totalDuration.addAndGet(duration);
            
            log.info("Task {} completed in {}ms, success: {}", taskId, duration, success);
        }
    }

    /**
     * 记录文件处理
     */
    public void recordFileProcessed(Long taskId, long fileSize, long recordCount, long duration) {
        TaskMetrics metrics = taskMetricsMap.get(taskId);
        if (metrics != null) {
            metrics.filesProcessed.incrementAndGet();
            metrics.totalFileSize.addAndGet(fileSize);
            metrics.totalRecords.addAndGet(recordCount);
            metrics.totalProcessingTime.addAndGet(duration);
        }
        
        // 更新全局指标
        globalMetrics.totalFiles.incrementAndGet();
        globalMetrics.totalFileSize.addAndGet(fileSize);
        globalMetrics.totalRecords.addAndGet(recordCount);
    }

    /**
     * 记录解析性能
     */
    public void recordParsePerformance(Long taskId, long duration, long recordCount) {
        TaskMetrics metrics = taskMetricsMap.get(taskId);
        if (metrics != null) {
            metrics.totalParseTime.addAndGet(duration);
        }
        
        globalMetrics.totalParseTime.addAndGet(duration);
    }

    /**
     * 记录加载性能
     */
    public void recordLoadPerformance(Long taskId, long duration, long recordCount) {
        TaskMetrics metrics = taskMetricsMap.get(taskId);
        if (metrics != null) {
            metrics.totalLoadTime.addAndGet(duration);
        }
        
        globalMetrics.totalLoadTime.addAndGet(duration);
    }

    /**
     * 获取任务指标
     */
    public TaskMetrics getTaskMetrics(Long taskId) {
        return taskMetricsMap.get(taskId);
    }

    /**
     * 获取全局指标
     */
    public GlobalMetrics getGlobalMetrics() {
        return globalMetrics;
    }

    /**
     * 清理任务指标
     */
    public void clearTaskMetrics(Long taskId) {
        taskMetricsMap.remove(taskId);
    }

    /**
     * 获取性能统计
     */
    public Map<String, Object> getStatistics() {
        Map<String, Object> stats = new ConcurrentHashMap<>();
        
        // 全局统计
        stats.put("totalTasks", globalMetrics.totalTasks.get());
        stats.put("successTasks", globalMetrics.successTasks.get());
        stats.put("failedTasks", globalMetrics.failedTasks.get());
        stats.put("totalFiles", globalMetrics.totalFiles.get());
        stats.put("totalRecords", globalMetrics.totalRecords.get());
        stats.put("totalFileSize", globalMetrics.totalFileSize.get());
        
        // 平均性能
        long totalTasks = globalMetrics.totalTasks.get();
        if (totalTasks > 0) {
            stats.put("avgTaskDuration", globalMetrics.totalDuration.get() / totalTasks);
            stats.put("avgParseTime", globalMetrics.totalParseTime.get() / totalTasks);
            stats.put("avgLoadTime", globalMetrics.totalLoadTime.get() / totalTasks);
        }
        
        long totalFiles = globalMetrics.totalFiles.get();
        if (totalFiles > 0) {
            stats.put("avgFileSize", globalMetrics.totalFileSize.get() / totalFiles);
        }
        
        long totalRecords = globalMetrics.totalRecords.get();
        if (totalRecords > 0) {
            long totalParseTime = globalMetrics.totalParseTime.get();
            long totalLoadTime = globalMetrics.totalLoadTime.get();
            if (totalParseTime > 0) {
                stats.put("parseRecordsPerSecond", totalRecords * 1000 / totalParseTime);
            }
            if (totalLoadTime > 0) {
                stats.put("loadRecordsPerSecond", totalRecords * 1000 / totalLoadTime);
            }
        }
        
        // 当前运行任务数
        stats.put("runningTasks", taskMetricsMap.size());
        
        return stats;
    }

    /**
     * 任务性能指标
     */
    @Data
    public static class TaskMetrics {
        private Long taskId;
        private long startTime;
        private long endTime;
        private boolean success;
        
        private AtomicLong filesProcessed = new AtomicLong(0);
        private AtomicLong totalFileSize = new AtomicLong(0);
        private AtomicLong totalRecords = new AtomicLong(0);
        private AtomicLong totalProcessingTime = new AtomicLong(0);
        private AtomicLong totalParseTime = new AtomicLong(0);
        private AtomicLong totalLoadTime = new AtomicLong(0);
        
        public long getDuration() {
            return endTime - startTime;
        }
        
        public double getAvgFileSize() {
            long files = filesProcessed.get();
            return files > 0 ? (double) totalFileSize.get() / files : 0;
        }
        
        public double getAvgRecordsPerFile() {
            long files = filesProcessed.get();
            return files > 0 ? (double) totalRecords.get() / files : 0;
        }
        
        public double getThroughput() {
            long duration = getDuration();
            return duration > 0 ? (double) totalRecords.get() * 1000 / duration : 0;
        }
    }

    /**
     * 全局性能指标
     */
    @Data
    public static class GlobalMetrics {
        private AtomicLong totalTasks = new AtomicLong(0);
        private AtomicLong successTasks = new AtomicLong(0);
        private AtomicLong failedTasks = new AtomicLong(0);
        private AtomicLong totalFiles = new AtomicLong(0);
        private AtomicLong totalRecords = new AtomicLong(0);
        private AtomicLong totalFileSize = new AtomicLong(0);
        private AtomicLong totalDuration = new AtomicLong(0);
        private AtomicLong totalParseTime = new AtomicLong(0);
        private AtomicLong totalLoadTime = new AtomicLong(0);
    }
}
